home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / as / dist / app.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-18  |  7.3 KB  |  381 lines

  1. /* This is the Assembler Pre-Processor
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* App, the assembler pre-processor.  This pre-processor strips out excess
  21.    spaces, turns single-quoted characters into a decimal constant, and turns
  22.    # <number> <filename> <garbage> into a .line <number>;.file <filename> pair.
  23.    This needs better error-handling.
  24.  */
  25. #include <stdio.h>
  26. #ifdef USG
  27. #define bzero(s,n) memset(s,0,n)
  28. #endif
  29.  
  30. static char    lex [256];
  31. static char    symbol_chars[] = 
  32.     "$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  33.  
  34. extern char comment_chars[];
  35. extern char line_comment_chars[];
  36.  
  37. #define LEX_IS_SYMBOL_COMPONENT        (1)
  38. #define LEX_IS_WHITESPACE        (2)
  39. #define LEX_IS_LINE_SEPERATOR        (4)
  40. #define LEX_IS_COMMENT_START        (8)    /* JF added these two */
  41. #define LEX_IS_LINE_COMMENT_START    (16)
  42. #define IS_SYMBOL_COMPONENT(c)        (lex [c] & LEX_IS_SYMBOL_COMPONENT)
  43. #define IS_WHITESPACE(c)        (lex [c] & LEX_IS_WHITESPACE)
  44. #define IS_LINE_SEPERATOR(c)        (lex [c] & LEX_IS_LINE_SEPERATOR)
  45. #define IS_COMMENT(c)            (lex [c] & LEX_IS_COMMENT_START)
  46. #define IS_LINE_COMMENT(c)        (lex [c] & LEX_IS_LINE_COMMENT_START)
  47.  
  48. void
  49. do_scrub_begin()
  50. {
  51.     char *p;
  52.  
  53.     bzero (lex, sizeof(lex));        /* Trust NOBODY! */
  54.     lex [' ']        |= LEX_IS_WHITESPACE;
  55.     lex ['\t']        |= LEX_IS_WHITESPACE;
  56.     for (p =symbol_chars;*p;++p)
  57.         lex [*p] |= LEX_IS_SYMBOL_COMPONENT;
  58.     lex ['\n']        |= LEX_IS_LINE_SEPERATOR;
  59. #ifdef DONTDEF
  60.     lex [':']        |= LEX_IS_LINE_SEPERATOR;
  61. #endif
  62.     lex [';']        |= LEX_IS_LINE_SEPERATOR;
  63.     for (p=comment_chars;*p;p++)
  64.         lex[*p] |= LEX_IS_COMMENT_START;
  65.     for (p=line_comment_chars;*p;p++)
  66.         lex[*p] |= LEX_IS_LINE_COMMENT_START;
  67. }
  68.  
  69. FILE *scrub_file;
  70.  
  71. int
  72. scrub_from_file()
  73. {
  74.     return getc(scrub_file);
  75. }
  76.  
  77. void
  78. scrub_to_file(ch)
  79. int ch;
  80. {
  81.     ungetc(ch,scrub_file);
  82. }
  83.  
  84. char *scrub_string;
  85. char *scrub_last_string;
  86.  
  87. int
  88. scrub_from_string()
  89. {
  90.     return scrub_string == scrub_last_string ? EOF : *scrub_string++;
  91. }
  92.  
  93. void
  94. scrub_to_string(ch)
  95. int ch;
  96. {
  97.     *--scrub_string=ch;
  98. }
  99.  
  100. int
  101. do_scrub_next_char(get,unget)
  102. int (*get)();
  103. void (*unget)();
  104. /* FILE *fp; */
  105. {
  106.     /* State 0: beginning of normal line
  107.         1: After first whitespace on normal line (flush more white)
  108.         2: After first non-white on normal line (keep 1white)
  109.         3: after second white on normal line (flush white)
  110.         4: after putting out a .line, put out digits
  111.         5: parsing a string, then go to old-state
  112.         6: putting out \ escape in a "d string.
  113.         7: After putting out a .file string, flush until newline.
  114.         -1: output string in out_string and go to the state in old_state
  115.         -2: flush text until a '*' '/' is seen, then go to state old_state
  116.     */
  117.  
  118.     static state;
  119.     static old_state;
  120.     static char *out_string;
  121.     static char out_buf[20];
  122.     static add_newlines = 0;
  123.     int ch;
  124.  
  125.     if(state==-1) {
  126.         ch= *out_string++;
  127.         if(*out_string==0) {
  128.             state=old_state;
  129.             old_state=3;
  130.         }
  131.         return ch;
  132.     }
  133.     if(state==-2) {
  134.         for(;;) {
  135.             do ch=(*get)();
  136.             while(ch!=EOF && ch!='\n' && ch!='*');
  137.             if(ch=='\n' || ch==EOF)
  138.                 return ch;
  139.              ch=(*get)();
  140.              if(ch==EOF || ch=='/')
  141.                  break;
  142.             (*unget)(ch);
  143.         }
  144.         state=old_state;
  145.         return ' ';
  146.     }
  147.     if(state==4) {
  148.         ch=(*get)();
  149.         if(ch==EOF || (ch>='0' && ch<='9'))
  150.             return ch;
  151.         else {
  152.             while(ch!=EOF && IS_WHITESPACE(ch))
  153.                 ch=(*get)();
  154.             if(ch=='"') {
  155.                 (*unget)(ch);
  156.                 out_string="; .file ";
  157.                 old_state=7;
  158.                 state= -1;
  159.                 return *out_string++;
  160.             } else {
  161.                 while(ch!=EOF && ch!='\n')
  162.                     ch=(*get)();
  163.                 return ch;
  164.             }
  165.         }
  166.     }
  167.     if(state==5) {
  168.         ch=(*get)();
  169.         if(ch=='"') {
  170.             state=old_state;
  171.             return '"';
  172.         } else if(ch=='\\') {
  173.             state=6;
  174.             return ch;
  175.         } else if(ch==EOF) {
  176.             as_warn("End of file in string: inserted '\"'");
  177.              state=old_state;
  178.             (*unget)('\n');
  179.             return '"';
  180.         } else {
  181.             return ch;
  182.         }
  183.     }
  184.     if(state==6) {
  185.         state=5;
  186.         ch=(*get)();
  187.         switch(ch) {
  188.             /* This is neet.  Turn "string
  189.                more string" into "string\n  more string"
  190.              */
  191.         case '\n':
  192.             (*unget)('n');
  193.             add_newlines++;
  194.             return '\\';
  195.  
  196.         case '"':
  197.         case '\\':
  198.         case 'b':
  199.         case 'f':
  200.         case 'n':
  201.         case 'r':
  202.         case 't':
  203.         case '0':
  204.         case '1':
  205.         case '2':
  206.         case '3':
  207.         case '4':
  208.         case '5':
  209.         case '6':
  210.         case '7':
  211.             break;
  212.         default:
  213.             as_warn("Unknown escape '\\%c' in string",ch);
  214.             break;
  215.  
  216.         case EOF:
  217.             as_warn("End of file in string: '\"' inserted");
  218.             return '"';
  219.         }
  220.         return ch;
  221.     }
  222.  
  223.     if(state==7) {
  224.         do ch= (*get)();
  225.         while(ch!='\n');
  226.         state=0;
  227.         return ch;
  228.     }
  229.  
  230.  flushchar:
  231.     ch=(*get)();
  232.     switch(ch) {
  233.     case ' ':
  234.     case '\t':
  235.         do ch=(*get)();
  236.         while(ch!=EOF && IS_WHITESPACE(ch));
  237.         if(ch==EOF)
  238.             return ch;
  239.         if(IS_COMMENT(ch) || (state==0 && IS_LINE_COMMENT(ch)) || ch=='/' || IS_LINE_SEPERATOR(ch)) {
  240.             (*unget)(ch);
  241.             goto flushchar;
  242.         }
  243.         (*unget)(ch);
  244.         if(state==0 || state==2) {
  245.             state++;
  246.             return ' ';
  247.         } else goto flushchar;
  248.  
  249.     case '/':
  250.         ch=(*get)();
  251.         if(ch=='*') {
  252.             for(;;) {
  253.                 do {
  254.                     ch=(*get)();
  255.                     if(ch=='\n')
  256.                         add_newlines++;
  257.                 } while(ch!=EOF && ch!='*');
  258.                 ch=(*get)();
  259.                 if(ch==EOF || ch=='/')
  260.                     break;
  261.                 (*unget)(ch);
  262.             }
  263.             if(ch==EOF)
  264.                 as_warn("End of file in '/' '*' string");
  265.  
  266.             (*unget)(' ');
  267.             goto flushchar;
  268.         } else {
  269.             if(IS_COMMENT('/') || (state==0 && IS_LINE_COMMENT('/'))) {
  270.                 ch='/';
  271.                 goto deal_misc;
  272.             }
  273.             if(ch!=EOF)
  274.                 (*unget)(ch);
  275.             return '/';
  276.         }
  277.         break;
  278.  
  279.     case '"':
  280.         old_state=state;
  281.         state=5;
  282.         return '"';
  283.         break;
  284.  
  285.     case '\'':
  286.         ch=(*get)();
  287.         if(ch==EOF) {
  288.             as_warn("End-of-file after a '");
  289.             ch=0;
  290.         }
  291.         sprintf(out_buf,"(%d)",ch&0xff);
  292.         old_state=state;
  293.         state= -1;
  294.         out_string=out_buf;
  295.         return *out_string++;
  296.  
  297.     case ':':
  298.         if(state!=3)
  299.             state=0;
  300.         return ch;
  301.  
  302.     case '\n':
  303.         if(add_newlines) {
  304.             --add_newlines;
  305.             (*unget)(ch);
  306.         }
  307.     case ';':
  308.         state=0;
  309.         return ch;
  310.  
  311.     default:
  312.     deal_misc:
  313.         if(state==0 && IS_LINE_COMMENT(ch)) {
  314.             do ch=(*get)();
  315.             while(ch!=EOF && IS_WHITESPACE(ch));
  316.             if(ch==EOF) {
  317.                 as_warn("Unexpected EOF in comment");
  318.                 return '\n';
  319.             }
  320.             if(ch<'0' || ch>'9') {
  321.                 do ch=(*get)();
  322.                 while(ch!=EOF && ch!='\n');
  323.                 if(ch==EOF)
  324.                     as_warn("Unexpected EOF in Comment");
  325.                 state=0;
  326.                 return '\n';
  327.             }
  328.             (*unget)(ch);
  329.             old_state=4;
  330.             state= -1;
  331.             out_string=".line ";
  332.             return *out_string++;
  333.  
  334.         } else if(IS_COMMENT(ch)) {
  335.             do ch=(*get)();
  336.             while(ch!=EOF && ch!='\n');
  337.             if(ch==EOF)
  338.                 as_warn("Unexpected EOF in comment");
  339.             state=0;
  340.             return '\n';
  341.  
  342.         } else if(state==0) {
  343.             state=2;
  344.             return ch;
  345.         } else if(state==1) {
  346.             state=2;
  347.             return ch;
  348.         } else {
  349.             return ch;
  350.  
  351.         }
  352.     case EOF:
  353.         if(state==0)
  354.             return ch;
  355.         as_warn("End-of-File not at end of a line");
  356.     }
  357.     return -1;
  358. }
  359.  
  360. #ifdef TEST
  361.  
  362. char comment_chars[] = "|";
  363. char line_comment_chars[] = "#";
  364.  
  365. main()
  366. {
  367.     int    ch;
  368.  
  369.     app_begin();
  370.     while((ch=do_scrub_next_char(stdin))!=EOF)
  371.         putc(ch,stdout);
  372. }
  373.  
  374. as_warn(str)
  375. char *str;
  376. {
  377.     fputs(str,stderr);
  378.     putc('\n',stderr);
  379. }
  380. #endif
  381.